package com.estate.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.estate.common.constant.HttpStatus;
import com.estate.common.core.domain.entity.SysUser;
import com.estate.common.core.domain.entity.TransactionData;
import com.estate.common.core.page.TableDataInfo;
import com.estate.common.utils.PageOutPutBean;
import com.estate.common.utils.PageQuery;
import com.estate.common.utils.PageUtils;
import com.estate.system.domain.Enquiry;
import com.estate.system.domain.Listing;
import com.estate.system.domain.report.boss.PropertyTypeDistribution;
import com.estate.system.domain.report.boss.TransactionTypeDistribution;
import com.estate.system.domain.report.boss.agentperformance.AgentStats;
import com.estate.system.domain.report.boss.agentperformance.ChartData;
import com.estate.system.domain.report.boss.listing.PriceRangeDistribution;
import com.estate.system.domain.report.boss.listing.TransactionPropertyHeatmap;
import com.estate.system.domain.vo.AgentPropertyDistributionResult;
import com.estate.system.domain.vo.HomeSaleDataView;
import com.estate.system.domain.vo.ListingQueryBo;
import com.estate.system.domain.vo.SuburbDetailVo;
import com.estate.system.mapper.DataEnquiryMapper;
import com.estate.system.mapper.DataListingsMapper;
import com.estate.system.mapper.SysUserMapper;
import com.estate.system.service.IDataListingsService;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.estate.common.utils.PageUtils.startPage;
import static com.estate.system.service.impl.TransactionDataServiceImpl.pageTransform2PageOutPutBean;

/**
 * 房源 业务层处理
 *
 * @author simon
 */
@Service
public class DataListingsServiceImpl extends ServiceImpl<DataListingsMapper, Listing> implements IDataListingsService {

    private static final Logger log = LoggerFactory.getLogger(DataListingsServiceImpl.class);

    @Resource
    private DataListingsMapper dataListingsMapper;
    @Autowired
    private SysUserMapper userMapper;

    @Override
    public List<Map<String, Object>> getListingCountByArea(Map<String, Object> param) {
        log.info("获取近七天新增房产数量请求参数={}", param);
        List<Map<String, Object>> listingCountByArea = new ArrayList<>();
        try {
            // 获取悉尼（澳大利亚东部）的当前时间
            ZoneId australiaSydney = ZoneId.of("Australia/Sydney");
            ZonedDateTime now = ZonedDateTime.now(australiaSydney);
            // 计算7天前的时间
            int sevenDays = param.get("XDays") == null ? 7 : Integer.parseInt(param.get("XDays").toString());
            ZonedDateTime sevenDaysAgo = now.minusDays(sevenDays);
            SysUser sysUser = new SysUser();
            List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());

            // 设置日期时间格式化器
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            listingCountByArea = dataListingsMapper.getListingCountByArea(sevenDaysAgo.format(formatter), now.format(formatter), emailList);
        } catch (Exception e) {
            log.error("获取近七天新增房产数量异常......", e);
        }
        return listingCountByArea;
    }

    @Override
    public Page<HomeSaleDataView> getDataView(HomeSaleDataView bo) {
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        bo.setEmailList(emailList);
        return dataListingsMapper.selectListingPage(PageUtils.getPage(bo), bo);
    }

    public List<PropertyTypeDistribution> generatePropertyTypeData(Map<String, Object> paramData) {
        List<PropertyTypeDistribution> propertyTypeDataList = new ArrayList<>();
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        List<Map<String, Object>> propertyTypeList = dataListingsMapper.generatePropertyTypeData(paramData, emailList);
        propertyTypeList.forEach(propertyTypeData -> {
            propertyTypeDataList.add(new PropertyTypeDistribution(propertyTypeData.get("type").toString(), Double.parseDouble(propertyTypeData.get("percentage").toString())));
        });
        return propertyTypeDataList;
    }

    public List<TransactionTypeDistribution> generateTransactionTypeData(Map<String, Object> paramData) {
        List<TransactionTypeDistribution> transactionTypeDistributions = new ArrayList<>();
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        List<Map<String, Object>> propertyTypeList = dataListingsMapper.generateTransactionTypeData(paramData, emailList);
        propertyTypeList.forEach(propertyTypeData -> {
            transactionTypeDistributions.add(new TransactionTypeDistribution(propertyTypeData.get("count").toString(), Double.parseDouble(propertyTypeData.get("percentage").toString())));
        });
        return transactionTypeDistributions;
    }

    public List<PriceRangeDistribution> generatePriceRangeData(Map<String, Object> paramData) {
        List<PriceRangeDistribution> priceRangeDistributionList = new ArrayList<>();
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        List<Map<String, Object>> propertyTypeList =  dataListingsMapper.generatePriceRangeData(paramData,emailList);
        propertyTypeList.forEach(propertyTypeData -> {
            Object percentage = propertyTypeData.get("percentage");
            double percentageDouble = 0d;
            if(!Objects.isNull(percentage)){
                percentageDouble = Double.parseDouble(percentage.toString());
            }
            priceRangeDistributionList.add(new PriceRangeDistribution(propertyTypeData.get("price_range").toString(), percentageDouble , Integer.parseInt(propertyTypeData.get("count").toString())));
        });
        return priceRangeDistributionList;
    }

    public List<TransactionPropertyHeatmap> generateHeatmapData(Map<String, Object> paramData) {
        List<TransactionPropertyHeatmap> transactionPropertyHeatmaps = new ArrayList<>();
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        List<Map<String, Object>> propertyTypeList = dataListingsMapper.generateHeatmapData(paramData, emailList);
        for (Map<String, Object> stringObjectMap : propertyTypeList) {
            transactionPropertyHeatmaps.add(new TransactionPropertyHeatmap(stringObjectMap.get("transactiontype").toString(), stringObjectMap.get("propertytype").toString(), Integer.parseInt(stringObjectMap.get("transactioncount").toString())));
        }
        return transactionPropertyHeatmaps;
    }

    public ChartData createPropertyType(Map<String, Object> paramData) {
        ChartData chartData = new ChartData();
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        List<AgentPropertyDistributionResult> agentAndListingPropertyList = dataListingsMapper.createPropertyType(paramData, emailList);
        Map<String, List<AgentPropertyDistributionResult>> resultMap = agentAndListingPropertyList.stream()
                .collect(Collectors.toMap(
                        AgentPropertyDistributionResult::getAgentName, // key映射
                        item -> {
                            List<AgentPropertyDistributionResult> list = new ArrayList<>();
                            list.add(item);
                            return list;
                        }, // value映射
                        (existingList, newList) -> { // 合并函数（处理key冲突）
                            existingList.addAll(newList);
                            return existingList;
                        }
                ));
        resultMap.forEach((agentName, agentPropertyDistributionResultList) -> {
            AgentStats agent = new AgentStats("agentName");
            for (AgentPropertyDistributionResult agentPropertyDistributionResult : agentPropertyDistributionResultList) {
                agent.addPropertyType(agentPropertyDistributionResult.getPropertyType(), Integer.parseInt(agentPropertyDistributionResult.getPropertyCount()));
            }
        });
        return chartData;
    }

    /**
     * 获取所有未映射的房产地址
     * @return
     */
    public List<Listing> selectListingsAll() {
        return dataListingsMapper.selectListingsAll();
    }

    public String getKeyFindings(String updateDate,String department) {
        return dataListingsMapper.getKeyFindings(updateDate,department);

    }

    public String getMarketGrowthPotential(String updateDate ) {
        return dataListingsMapper.getMarketGrowthPotential(updateDate);

    }

    public Map<String, List<SuburbDetailVo>> getSuburbDetail(Map<String, Object> paramData) {
        SysUser sysUser = new SysUser();
        List<String> emailList = userMapper.selectUserList(sysUser).stream().map(SysUser::getEmail).collect(Collectors.toList());
        List<SuburbDetailVo> suburbDetailVoList = dataListingsMapper.getSuburbDetail(paramData,emailList);
        Map<String,List<SuburbDetailVo>> result = Maps.newHashMap();
        result.put("suburbDetailVoList",suburbDetailVoList);
        return result;

    }

    public Map<String, Object> getTotalAIEngineCall(Map<String, Object> paramData) {
        ZoneId australiaSydney = ZoneId.of("Australia/Sydney");
        ZonedDateTime now = ZonedDateTime.now(australiaSydney);
        // 计算7天前的时间
        ZonedDateTime dayBeforeYesterday = now.minusDays(2);
        ZonedDateTime yesterday = now.minusDays(1);

        // 设置日期时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return dataListingsMapper.getTotalAIEngineCall(paramData,dayBeforeYesterday.format(formatter),yesterday.format(formatter));
    }

    public Map<String, Object> getDataSourceStatus(Map<String, Object> paramData) {
        ZoneId australiaSydney = ZoneId.of("Australia/Sydney");
        ZonedDateTime now = ZonedDateTime.now(australiaSydney);

        // 设置日期时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return dataListingsMapper.getDataSourceStatus(paramData,now.format(formatter));
    }

    public Map<String, Object> getDataProcessJobDetail(Map<String, Object> paramData) {
        return dataListingsMapper.getDataProcessJobDetail(paramData);
    }
}
